package com.tiecode.rhelper;

import com.qiplat.api.log.Logger;
import com.qiplat.api.project.Project;
import com.qiplat.api.project.ProjectVariant;
import com.qiplat.api.project.TaskedProject;
import com.qiplat.api.project.task.BaseTask;
import com.qiplat.api.project.task.Task;
import com.qiplat.api.project.task.exception.TaskInterruptError;
import com.qiplat.api.project.task.input.Inputs;
import com.qiplat.api.project.task.output.Outputs;
import com.qiplat.develop.util.firstparty.file.FileUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ModifyJavaFileTask extends BaseTask {
    public final static String ID = "modifyJavaFile";
    private final static String NAME = "修改外部Java文件";
    private static final Pattern manifestPattern = Pattern.compile("\\s*(package)\\s*(=)\\s*(\")([a-zA-Z0-9.]+)(\")");
    private static final Pattern javaPattern = Pattern.compile("\\s*(package)\\s*(\\b)\\s*([a-zA-Z0-9.]+)\\s*;");

    private TaskedProject project;
    private String packageName;
    private String packagePath;

    @Override
    public String getId() {
        return ID;
    }

    @Override
    public String getName() {
        return NAME;
    }

    @Override
    public void prepare(Project project, ProjectVariant variant, Logger logger) {
        super.prepare(project, variant, logger);
        this.project = (TaskedProject) project;
    }

    @Override
    public void execute() throws TaskInterruptError {
        Task compileWithTiecodec = project.getTask("compileWithTiecodec");
        String srcPath = compileWithTiecodec.getIntermediatePath("src");
        String manifestPath = compileWithTiecodec.getIntermediatePath("AndroidManifest.xml");
        try {
            this.packageName = getRPackage(manifestPath);
            this.packagePath = packageName.replace('.', '/');
            scanAndModifyFiles(new File(srcPath));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void scanAndModifyFiles(File file) throws IOException {
        if (file.isFile()
                && file.getName().endsWith(".java")
                && !file.getName().startsWith("rn_")
                && !file.getPath().contains(packagePath)
        ) {
            modifyFile(file);
        } else if (file.isDirectory()) {
            File[] listFiles = file.listFiles();
            if (listFiles == null) return;
            for (File listFile : listFiles) {
                scanAndModifyFiles(listFile);
            }
        }
    }

    private void modifyFile(File file) throws IOException {
        String text = FileUtils.readFile(file);
        Matcher matcher = javaPattern.matcher(text);
        while (matcher.find()) {
            String group = matcher.group(0);
            text = text.replace(group, group + " import " + packageName + ".R;");
            FileUtils.writeFile(text, file);
            break;
        }
    }

    private String getRPackage(String path) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path)));
        String line;
        while ((line = reader.readLine()) != null) {
            if (manifestPattern.matcher(line).find()) {
                break;
            }
        }
        if (line != null) {
            String name = line.substring(line.indexOf('"') + 1, line.lastIndexOf('"'));
            return name;
        } else {
            throw new IOException("R package not found");
        }
    }

    @Override
    public Inputs getInputs() {
        return null;
    }

    @Override
    public Outputs getOutputs() {
        return null;
    }
}
